package com.example.securitydemo.configuration.security;

import com.example.securitydemo.model.pojo.TokenUser;
import com.example.securitydemo.utils.JwtUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 这个过滤器只有在每次登录的时候才会调用
 */
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    public TokenLoginFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        // 获取请求中的 username 和 password;
        String username = obtainUsername(request);
        username = (username != null) ? username : "";
        username = username.trim();
        String password = obtainPassword(request);
        password = (password != null) ? password : "";
        // 构造securityToken 进行认证
        // 这里直接用密码进行构造，security会自己进行passwordEncode
        // 但是security User对象并没有进行passwordEncode
        // 如果数据库中的密码被加密了，这里需要对password进行加密处理
        // password = encryptPassword(password)
        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(username,password);
        return authenticationManager.authenticate(authToken);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        // 生成token直接返回。前端拿到 token 自行存入
        User principal = (User) authResult.getPrincipal();
        String username = principal.getUsername();
        List<String> authorityList = principal.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
        String token = JwtUtils.generateUserToken(new TokenUser(username, authorityList));
//        response.addCookie(new Cookie("token", token));
        PrintWriter writer = response.getWriter();
        writer.println(token);
        writer.close();
        // 至此登录成功做的事情完成了
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        PrintWriter writer = response.getWriter();
        writer.println("认证失败!");
        writer.close();
    }

}
